"""
基础监控器

提供监控系统的基础功能和抽象接口。
"""

from abc import ABC, abstractmethod
from enum import Enum
from typing import Dict, List, Optional, Any, Callable, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import asyncio
import threading
import time
from decimal import Decimal


class MonitorType(Enum):
    """监控类型枚举"""
    PERFORMANCE = "performance"  # 性能监控
    RISK = "risk"  # 风险监控
    SYSTEM = "system"  # 系统监控
    TRADING = "trading"  # 交易监控
    PORTFOLIO = "portfolio"  # 组合监控
    MARKET = "market"  # 市场监控
    ALERT = "alert"  # 告警监控
    CUSTOM = "custom"  # 自定义监控


class MonitorStatus(Enum):
    """监控状态枚举"""
    STOPPED = "stopped"  # 已停止
    STARTING = "starting"  # 启动中
    RUNNING = "running"  # 运行中
    PAUSED = "paused"  # 已暂停
    STOPPING = "stopping"  # 停止中
    ERROR = "error"  # 错误状态


class MonitorLevel(Enum):
    """监控级别枚举"""
    DEBUG = "debug"  # 调试级别
    INFO = "info"  # 信息级别
    WARNING = "warning"  # 警告级别
    ERROR = "error"  # 错误级别
    CRITICAL = "critical"  # 严重级别


@dataclass
class MonitorEvent:
    """监控事件"""
    monitor_id: str  # 监控器ID
    event_type: str  # 事件类型
    level: MonitorLevel  # 事件级别
    message: str  # 事件消息
    data: Dict[str, Any] = field(default_factory=dict)  # 事件数据
    timestamp: datetime = field(default_factory=datetime.now)  # 事件时间
    source: Optional[str] = None  # 事件源


@dataclass
class MonitorConfig:
    """监控配置"""
    monitor_id: str  # 监控器ID
    monitor_type: MonitorType  # 监控类型
    name: str  # 监控器名称
    description: str = ""  # 监控器描述
    
    # 监控参数
    interval: float = 1.0  # 监控间隔（秒）
    timeout: float = 30.0  # 超时时间（秒）
    max_retries: int = 3  # 最大重试次数
    
    # 启用状态
    enabled: bool = True  # 是否启用
    auto_start: bool = False  # 是否自动启动
    
    # 阈值配置
    thresholds: Dict[str, Any] = field(default_factory=dict)  # 阈值配置
    
    # 回调配置
    callbacks: Dict[str, List[Callable]] = field(default_factory=dict)  # 回调函数
    
    # 其他配置
    metadata: Dict[str, Any] = field(default_factory=dict)  # 元数据


@dataclass
class MonitorMetrics:
    """监控指标"""
    monitor_id: str  # 监控器ID
    metrics: Dict[str, Any] = field(default_factory=dict)  # 指标数据
    timestamp: datetime = field(default_factory=datetime.now)  # 指标时间
    
    def get_metric(self, key: str, default: Any = None) -> Any:
        """获取指标值"""
        return self.metrics.get(key, default)
    
    def set_metric(self, key: str, value: Any) -> None:
        """设置指标值"""
        self.metrics[key] = value
    
    def update_metrics(self, metrics: Dict[str, Any]) -> None:
        """更新指标"""
        self.metrics.update(metrics)
        self.timestamp = datetime.now()


class BaseMonitor(ABC):
    """基础监控器抽象类"""
    
    def __init__(self, config: MonitorConfig):
        """
        初始化监控器
        
        Args:
            config: 监控配置
        """
        self.config = config
        self.status = MonitorStatus.STOPPED
        self.metrics = MonitorMetrics(config.monitor_id)
        self.events: List[MonitorEvent] = []
        
        # 运行控制
        self._running = False
        self._thread: Optional[threading.Thread] = None
        self._stop_event = threading.Event()
        
        # 统计信息
        self.start_time: Optional[datetime] = None
        self.last_check_time: Optional[datetime] = None
        self.check_count = 0
        self.error_count = 0
        
        # 回调函数
        self._event_callbacks: List[Callable[[MonitorEvent], None]] = []
        self._metrics_callbacks: List[Callable[[MonitorMetrics], None]] = []
    
    @abstractmethod
    async def check(self) -> MonitorMetrics:
        """
        执行监控检查
        
        Returns:
            MonitorMetrics: 监控指标
        """
        pass
    
    def start(self) -> None:
        """启动监控器"""
        if self.status == MonitorStatus.RUNNING:
            return
        
        self.status = MonitorStatus.STARTING
        self._running = True
        self._stop_event.clear()
        
        # 启动监控线程
        self._thread = threading.Thread(target=self._run_loop, daemon=True)
        self._thread.start()
        
        self.start_time = datetime.now()
        self.status = MonitorStatus.RUNNING
        
        self._emit_event(
            "monitor_started",
            MonitorLevel.INFO,
            f"监控器 {self.config.name} 已启动"
        )
    
    def stop(self) -> None:
        """停止监控器"""
        if self.status == MonitorStatus.STOPPED:
            return
        
        self.status = MonitorStatus.STOPPING
        self._running = False
        self._stop_event.set()
        
        # 等待线程结束
        if self._thread and self._thread.is_alive():
            self._thread.join(timeout=5.0)
        
        self.status = MonitorStatus.STOPPED
        
        self._emit_event(
            "monitor_stopped",
            MonitorLevel.INFO,
            f"监控器 {self.config.name} 已停止"
        )
    
    def pause(self) -> None:
        """暂停监控器"""
        if self.status == MonitorStatus.RUNNING:
            self.status = MonitorStatus.PAUSED
            self._emit_event(
                "monitor_paused",
                MonitorLevel.INFO,
                f"监控器 {self.config.name} 已暂停"
            )
    
    def resume(self) -> None:
        """恢复监控器"""
        if self.status == MonitorStatus.PAUSED:
            self.status = MonitorStatus.RUNNING
            self._emit_event(
                "monitor_resumed",
                MonitorLevel.INFO,
                f"监控器 {self.config.name} 已恢复"
            )
    
    def _run_loop(self) -> None:
        """监控运行循环"""
        while self._running and not self._stop_event.is_set():
            try:
                if self.status == MonitorStatus.RUNNING:
                    # 执行异步检查
                    loop = asyncio.new_event_loop()
                    asyncio.set_event_loop(loop)
                    
                    try:
                        metrics = loop.run_until_complete(self.check())
                        self.metrics = metrics
                        self.last_check_time = datetime.now()
                        self.check_count += 1
                        
                        # 调用指标回调
                        for callback in self._metrics_callbacks:
                            try:
                                callback(metrics)
                            except Exception as e:
                                self._emit_event(
                                    "callback_error",
                                    MonitorLevel.ERROR,
                                    f"指标回调执行失败: {e}"
                                )
                    finally:
                        loop.close()
                
                # 等待下次检查
                self._stop_event.wait(self.config.interval)
                
            except Exception as e:
                self.error_count += 1
                self.status = MonitorStatus.ERROR
                
                self._emit_event(
                    "monitor_error",
                    MonitorLevel.ERROR,
                    f"监控器执行错误: {e}",
                    {"error": str(e), "error_count": self.error_count}
                )
                
                # 错误恢复
                time.sleep(self.config.interval)
                if self._running:
                    self.status = MonitorStatus.RUNNING
    
    def _emit_event(
        self,
        event_type: str,
        level: MonitorLevel,
        message: str,
        data: Optional[Dict[str, Any]] = None
    ) -> None:
        """发出监控事件"""
        event = MonitorEvent(
            monitor_id=self.config.monitor_id,
            event_type=event_type,
            level=level,
            message=message,
            data=data or {},
            source=self.__class__.__name__
        )
        
        self.events.append(event)
        
        # 限制事件历史长度
        if len(self.events) > 1000:
            self.events = self.events[-500:]
        
        # 调用事件回调
        for callback in self._event_callbacks:
            try:
                callback(event)
            except Exception as e:
                print(f"事件回调执行失败: {e}")
    
    def add_event_callback(self, callback: Callable[[MonitorEvent], None]) -> None:
        """添加事件回调"""
        self._event_callbacks.append(callback)
    
    def add_metrics_callback(self, callback: Callable[[MonitorMetrics], None]) -> None:
        """添加指标回调"""
        self._metrics_callbacks.append(callback)
    
    def remove_event_callback(self, callback: Callable[[MonitorEvent], None]) -> None:
        """移除事件回调"""
        if callback in self._event_callbacks:
            self._event_callbacks.remove(callback)
    
    def remove_metrics_callback(self, callback: Callable[[MonitorMetrics], None]) -> None:
        """移除指标回调"""
        if callback in self._metrics_callbacks:
            self._metrics_callbacks.remove(callback)
    
    def get_status(self) -> Dict[str, Any]:
        """获取监控器状态"""
        uptime = None
        if self.start_time:
            uptime = (datetime.now() - self.start_time).total_seconds()
        
        return {
            "monitor_id": self.config.monitor_id,
            "name": self.config.name,
            "type": self.config.monitor_type.value,
            "status": self.status.value,
            "enabled": self.config.enabled,
            "uptime": uptime,
            "check_count": self.check_count,
            "error_count": self.error_count,
            "last_check_time": self.last_check_time.isoformat() if self.last_check_time else None,
            "metrics_count": len(self.metrics.metrics),
            "events_count": len(self.events)
        }
    
    def get_recent_events(self, count: int = 10) -> List[MonitorEvent]:
        """获取最近的事件"""
        return self.events[-count:] if self.events else []
    
    def get_events_by_level(self, level: MonitorLevel) -> List[MonitorEvent]:
        """按级别获取事件"""
        return [event for event in self.events if event.level == level]
    
    def clear_events(self) -> None:
        """清空事件历史"""
        self.events.clear()
    
    def update_config(self, config: MonitorConfig) -> None:
        """更新配置"""
        old_config = self.config
        self.config = config
        
        self._emit_event(
            "config_updated",
            MonitorLevel.INFO,
            f"监控器配置已更新",
            {
                "old_interval": old_config.interval,
                "new_interval": config.interval,
                "old_enabled": old_config.enabled,
                "new_enabled": config.enabled
            }
        )


class Monitor:
    """
    监控器管理器
    
    管理和协调多个监控器。
    """
    
    def __init__(self):
        """初始化监控器管理器"""
        self._monitors: Dict[str, BaseMonitor] = {}
        self._global_event_callbacks: List[Callable[[MonitorEvent], None]] = []
        self._global_metrics_callbacks: List[Callable[[MonitorMetrics], None]] = []
    
    def register_monitor(self, monitor: BaseMonitor) -> None:
        """
        注册监控器
        
        Args:
            monitor: 监控器实例
        """
        monitor_id = monitor.config.monitor_id
        
        if monitor_id in self._monitors:
            raise ValueError(f"监控器 {monitor_id} 已存在")
        
        self._monitors[monitor_id] = monitor
        
        # 添加全局回调
        monitor.add_event_callback(self._handle_global_event)
        monitor.add_metrics_callback(self._handle_global_metrics)
        
        # 自动启动
        if monitor.config.auto_start:
            monitor.start()
    
    def unregister_monitor(self, monitor_id: str) -> None:
        """
        注销监控器
        
        Args:
            monitor_id: 监控器ID
        """
        if monitor_id in self._monitors:
            monitor = self._monitors[monitor_id]
            monitor.stop()
            del self._monitors[monitor_id]
    
    def get_monitor(self, monitor_id: str) -> Optional[BaseMonitor]:
        """获取监控器"""
        return self._monitors.get(monitor_id)
    
    def start_monitor(self, monitor_id: str) -> None:
        """启动监控器"""
        if monitor_id in self._monitors:
            self._monitors[monitor_id].start()
    
    def stop_monitor(self, monitor_id: str) -> None:
        """停止监控器"""
        if monitor_id in self._monitors:
            self._monitors[monitor_id].stop()
    
    def start_all(self) -> None:
        """启动所有监控器"""
        for monitor in self._monitors.values():
            if monitor.config.enabled:
                monitor.start()
    
    def stop_all(self) -> None:
        """停止所有监控器"""
        for monitor in self._monitors.values():
            monitor.stop()
    
    def get_status_summary(self) -> Dict[str, Any]:
        """获取状态摘要"""
        total_monitors = len(self._monitors)
        running_monitors = len([m for m in self._monitors.values() if m.status == MonitorStatus.RUNNING])
        error_monitors = len([m for m in self._monitors.values() if m.status == MonitorStatus.ERROR])
        
        return {
            "total_monitors": total_monitors,
            "running_monitors": running_monitors,
            "error_monitors": error_monitors,
            "monitors": {
                monitor_id: monitor.get_status()
                for monitor_id, monitor in self._monitors.items()
            }
        }
    
    def get_all_events(self, level: Optional[MonitorLevel] = None) -> List[MonitorEvent]:
        """获取所有事件"""
        all_events = []
        for monitor in self._monitors.values():
            if level:
                all_events.extend(monitor.get_events_by_level(level))
            else:
                all_events.extend(monitor.events)
        
        # 按时间排序
        all_events.sort(key=lambda x: x.timestamp)
        return all_events
    
    def add_global_event_callback(self, callback: Callable[[MonitorEvent], None]) -> None:
        """添加全局事件回调"""
        self._global_event_callbacks.append(callback)
    
    def add_global_metrics_callback(self, callback: Callable[[MonitorMetrics], None]) -> None:
        """添加全局指标回调"""
        self._global_metrics_callbacks.append(callback)
    
    def _handle_global_event(self, event: MonitorEvent) -> None:
        """处理全局事件"""
        for callback in self._global_event_callbacks:
            try:
                callback(event)
            except Exception as e:
                print(f"全局事件回调执行失败: {e}")
    
    def _handle_global_metrics(self, metrics: MonitorMetrics) -> None:
        """处理全局指标"""
        for callback in self._global_metrics_callbacks:
            try:
                callback(metrics)
            except Exception as e:
                print(f"全局指标回调执行失败: {e}")